#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


#include "icar.h"
#include "icar_flat_msg.h"
#include "icar_end_param.h"
#include "icar_log.h"
#include "icar_utils.h"

struct icar_iovec *
flat_genricRes(int rsa, const char *number,
		struct flatRes *res)
{
	struct icar_iovec *iovec = NULL;
	uint8_t  data[MAX_PKG_LENGTH] = {  0 };
	int n = 0;
	uint16_t stmp;
	ICAR_HTONS(res->sequence);
	ICAR_HTONS(res->endId);
	data[n++] = res->result;

	if (rsa == ENCRYPT_NONE)
		iovec = icar_pkg_iovec(ICAR_FLAT_RESPONSE, number, data, n);

	return iovec;
}

struct icar_iovec *
flat_supplement_req(int rsa, const char *number, 
		struct supplement_req *req)
{
	return NULL;
}

struct icar_iovec *
flat_reg_response(int rsa, const char *number, struct regiser_res *res)
{
	uint16_t stmp;
	int n = 0;

	switch (res->result) {
	case 0:
		{
			uint8_t data[4096] =  { 0 };
			int count = 0;
			if (!res || !res->authcode) {
				return NULL;
			}
			ICAR_HTONS(res->sequence);
			data[n++] = 0;
			if (strlen(res->authcode) > sizeof(data)) 
			{
				icar_daemon(LOG_ERR, "Authentication code is too long to store in the data buffer");
				return NULL;
			}

			count = utf2Gbk(res->authcode, strlen(res->authcode)+1, &data[n], sizeof(data)-n);
			if (count < 0)
				return NULL;
			n += count;

			if (rsa == ENCRYPT_NONE)
				return icar_pkg_iovec(ICAR_FLAT_REGISTER_RES, number, data, n);
		}
		break;
	case 1:
	case 2:
	case 3:
	case 4:
		{
			uint8_t data[16] = { 0 };
			ICAR_HTONS(res->sequence);
			data[n++] = res->result;
			if (rsa == ENCRYPT_NONE)
				return icar_pkg_iovec(ICAR_FLAT_REGISTER_RES, number, data, n);
		}
	default:
		return NULL;
	}

	return NULL;
}

struct icar_iovec *
flat_get_end_param(const char *number)
{
	return icar_pkg_iovec(ICAR_GET_END_PARAM, number, NULL, 0);
}

struct icar_iovec *
flat_get_spec_param(int rsa, const char *number, uint32_t *list,
		size_t size)
{
	uint8_t data[1024] = { 0 };
	uint32_t ltmp;
	int n = 0;
	data[n++] = size;
	int i = 0;
	for ( ; i < size; i++)
	{
		ICAR_HTONL(list[i]);
	}
	if (rsa == ENCRYPT_NONE)
	{
		return icar_pkg_iovec(ICAR_GET_SPEC_END_PARAM, number, data, n);
	}
	return NULL;
}

struct icar_iovec *
flat_get_end_property(const char *number)
{
	return icar_pkg_iovec(ICAR_GET_END_PROPERTY, number, NULL, 0);
}

struct icar_iovec *
flat_end_update(int rsa, const char *number, struct flatUpdate *up)
{
	struct icar_iovec *iovec;
	uint8_t *data;
	uint32_t n;
	int count;
	uint32_t ltmp;
	iovec = NULL;
	data = NULL;
	n = count = 0;
	if (!up || !up->version || !up->data)
		return NULL;

	data = (uint8_t *)malloc(up->verLen + up->upLen + 12);
	if (!data)
		return NULL;
	memset(data, 0, up->verLen + up->upLen + 12);

	if (rsa == ENCRYPT_NONE) {
		data[n++] = up->type;
		memcpy(&data[n], up->manufacturer, 5);
		n += 5;

		count = utf2Gbk(up->version, up->verLen, &data[n+1], up->verLen+up->upLen+12 - n);
		if (count < 0) {
			free(data);
			return NULL;
		}
		data[n++] = (uint8_t)count;
		n += count;

		ltmp = htonl(up->upLen);
		memcpy(&data[n], &ltmp, 4);
		n += 4;
		memcpy(&data[n], up->data, up->upLen);
		n += up->upLen;

		iovec = icar_pkg_iovec(ICAR_ISSUE_END_UPGRADE, number, data, n);
		free(data);
	}

	return iovec;
}

struct icar_iovec *
flat_get_location(const char *number)
{
	return icar_pkg_iovec(ICAR_GET_LOCALINFO, number, NULL, 0);
}

struct icar_iovec *
flat_temp_local_ctrl(int rsa, const char *number, uint16_t interval, uint32_t validity)
{
	uint8_t data[8] = { 0 };
	uint16_t stmp;
	uint32_t ltmp;
	stmp = htons(interval);
	ltmp = htonl(validity);

	memcpy(data, &stmp, 2);
	memcpy(&data[2], &ltmp, 4);

	if (rsa == ENCRYPT_NONE)
		return icar_pkg_iovec(ICAR_TEMP_LOCAL_CONTROL, number, data, 6);

	return NULL;
}

struct icar_iovec *
flat_confirm_alarm(int rsa, const char *number, uint16_t sequence, uint32_t flag)
{
	uint8_t data[8] = { 0 };
	uint16_t stmp;
	uint32_t ltmp;
	stmp = htons(sequence);
	ltmp = htonl(flag);

	memcpy(data, &stmp, 2);
	memcpy(&data[2], &ltmp, 4);

	if (rsa == ENCRYPT_NONE)
		return icar_pkg_iovec(ICAR_MANUAL_CONFIRM_ALARM, number, data, 6);
	return NULL;
}

struct icar_iovec *
flat_textInfo_issue(int rsa, const char *number, uint8_t flag, char *info)
{
	struct icar_iovec *iovec;
	uint8_t data[4096] = { 0 };
	int n, count;
	int len;


	iovec = NULL;
	n = count = 0;

	if (rsa == ENCRYPT_NONE)
	{
		data[n++] = flag;
		if (info) {
			len = strlen(info)+1;
			count = utf2Gbk(info, len, &data[n], sizeof(data)-n);
			if (count < 0 || count > 1024)
			return NULL;
			n += count;
		} else
			data[n++] = 0;
		iovec = icar_pkg_iovec(ICAR_TEXT_INFO_ISSUE, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_ask_issue(int rsa, const char *number, struct flatAskIssue *ask)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	uint16_t stmp;
	int len;
	int count;
	int n;

	if (!ask || !ask->ask || !ask->answer)
		return NULL;

	n = count = 0;
	len = ask->askLen + ask->answerLen + 6;

	data = (uint8_t *)malloc(len);
	if (!data)
		return NULL;

	memset(data, 0, len);


	if (rsa == ENCRYPT_NONE) {
		data[n++] = ask->type;

		count = utf2Gbk(ask->ask, ask->askLen, &data[n+1], len - n);
		if (count < 0 || count > 255)
		{
			free(data);
			return NULL;
		}
		data[n++] = (uint8_t)count;
		n += count;

		data[n++] = ask->answerId;

		count = utf2Gbk(ask->answer, ask->answerLen, &data[n+2], len - n);
		if (count < 0 || count > 0xffff)
		{
			free(data);
			return NULL;
		}
		stmp = htons((uint16_t)count);
		memcpy(&data[n], &stmp, 2);
		n += 2;
		n += count;

		iovec = icar_pkg_iovec(ICAR_TEXT_INFO_ISSUE, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_infoMenu_set(int rsa, const char *number, struct flatInfoMenu *menu)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int n;
	int count;
	int len = 0;
	int i;

	if (!menu || menu->total <= 0)
		return NULL;

	for (i = 0; i < menu->total; i++)
		if (menu->iov[i].iov_base == NULL || menu->iov[i].iov_len <= 0)
			return NULL;
		else {
			len += menu->iov[i].iov_len;
		}

	len += 2 + 4 * i;

	data = (uint8_t *)malloc(len);
	if (data == NULL)
		return NULL;

	memset(data, 0, len);

	n = count = 0;
	if (rsa == ENCRYPT_NONE) {
		data[n++] = menu->type;
		data[n++] = menu->total;
		for (i = 0; i < menu->total; i++) {
			data[n++] = menu->iov[i].type;
			count = utf2Gbk(menu->iov[i].iov_base, menu->iov[i].iov_len, &data[n+2], len - n - 2);
			if (count <= 0) {
				free(data);
				return NULL;
			}
			data[n++] = menu->iov[i].iov_len >> 8 & 0xff;
			data[n++] = menu->iov[i].iov_len & 0xff;
			n += count;
		}

		iovec = icar_pkg_iovec(ICAR_INFO_HELPMENU_SET, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_infoServ(int rsa, const char *number, uint8_t type, char *info, uint16_t len)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int count = 0;

	data = (uint8_t *)malloc(len + 4);
	if (data == NULL)
		return NULL;
	memset(data, 0, len + 4);

	if (rsa == ENCRYPT_NONE) {
		data[0] = type & 0xff;
		if (!info) {
			data[1] = 1;
			data[2] = 0;
		} else {
			count = utf2Gbk(info, len, &data[3], len);
			if (count < 0) {
				free(data);
				return NULL;
			}
			data[1] = count >> 8 & 0xff;
			data[2] = count & 0xff;
		}
		iovec = icar_pkg_iovec(ICAR_INFO_SERVICE, number, data, 3+count);
	}

	free(data);
	return iovec;
}

/* 
   电话回拨 
	mark: 标志 0: 普通通话 1:监听
	phone: 电话号码
 */
struct icar_iovec *
flat_phoneCallback(int rsa, const char *number, uint8_t mark, char *phone)
{
	struct icar_iovec *iovec = NULL;
	int len;
	uint8_t data[32] = { 0 };

	if (phone == NULL)
		return NULL;

	len = strlen(phone) + 1;
	if (len > 20)
		return NULL;

	if (rsa == ENCRYPT_NONE) {
		data[0] = mark & 0xff;
		memcpy(&data[1], phone, len);
		iovec = icar_pkg_iovec(ICAR_PHONE_CALLBACK, number, data, len+1);
	}

	return iovec;
}

struct icar_iovec *
flat_setPhoneBook(int rsa, const char *number, struct flatPhone *book)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int len = 0;
	int count = 0;
	int i = 0, n = 0;

	if (!book || book->total == 0)
		return NULL;

	for (i = 0; i < book->total; i++) {
		if (book->co[i].nlen > 0 && book->co[i].clen > 0) {
			len += book->co[i].nlen;
			len += book->co[i].clen;
		}
	}

	len += 5 * i + 2;

	data = (uint8_t *)malloc(len);
	if (data == NULL)
		return NULL;
	memset(data, 0, len);

	n = 0;
	if (rsa == ENCRYPT_NONE) {
		data[n++] = book->type & 0xff;
		data[n++] = book->total & 0xff;
		for (i = 0; i < book->total; i++) {
			data[n++] = book->co[i].mark & 0xff;
			data[n++] = book->co[i].nlen;
			memcpy(&data[n], book->co[i].number, book->co[i].nlen);
			n += book->co[i].nlen;
			count = utf2Gbk(book->co[i].contac, book->co[i].clen,
					&data[n+1], book->co[i].clen);
			if (count < 0 || count > 255) {
				free(data);
				return NULL;
			}
			data[n++] = count & 0xff;
			n += count;
		}

		iovec = icar_pkg_iovec(ICAR_SET_PHONEBOOK, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_vehiCtrl(int rsa, const char *number, uint8_t flag)
{
	struct icar_iovec *iovec = NULL;

	if (rsa == ENCRYPT_NONE)
	{
		uint8_t data = flag & 0xff;
		iovec = icar_pkg_iovec(ICAR_VEICHLE_CONTROL, number, &data, 1); 
	}

	return iovec;
}

struct icar_iovec *
flat_setCycle(int rsa, const char *number, struct flatSetCycle *set)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int n;
	int len, count, i;
	uint32_t ltmp = 0;
	uint16_t stmp = 0;

	n = len = count = i = 0;

	if (!set || set->total <= 0)
		return NULL;

	len = set->total * sizeof(struct areaOption) + 8;

	data = (uint8_t *)malloc(len);
	if (!data)
		return NULL;

	memset(data, 0, len);

	if (rsa == ENCRYPT_NONE)
	{
		data[n++] = set->property & 0xff;
		data[n++] = set->total & 0xff;
		for (i = 0; i < set->total; i++) {
			ICAR_HTONL(set->ap[i].id);
			ICAR_HTONS(set->ap[i].property);
			ICAR_HTONL(set->ap[i].latitude);
			ICAR_HTONL(set->ap[i].longitude);
			ICAR_HTONL(set->ap[i].radius);
			if (set->ap[i].property & AREA_ATTRI_TIME)
			{
				memcpy(&data[n], set->ap[i].stime, 6);
				n += 6;
				memcpy(&data[n], set->ap[i].etime, 6);
				n += 6;
			}

			if (set->ap[i].property & AREA_ATTRI_RATELIMIT)
			{
				ICAR_HTONS(set->ap[i].speed);
				data[n++] = set->ap[i].otime & 0xff;
			}
		}

		iovec = icar_pkg_iovec(ICAR_SET_CYCLE_AREA, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_delCycle(int rsa, const char *number, struct flatDelCycle *del)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[1024] = { 0 };
	int n = 0;
	uint32_t ltmp = 0;

	if (del == NULL || del->total > 125)
		return NULL;

	if (rsa == ENCRYPT_NONE) {
		int i;
		data[n++] = del->total & 0xff;
		for (i = 0; i < del->total; i++) {
			ICAR_HTONL(del->id[i]);
		}
		iovec = icar_pkg_iovec(ICAR_DEL_CYCLE_AREA, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_setRectangle(int rsa, const char *number, struct flatSetRec *rec)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int n, i, len;
	uint32_t ltmp = 0;
	uint16_t stmp = 0;

	if (!rec || rec->total <= 0)
		return NULL;

	len = rec->total * sizeof(struct recArea) + 8;

	data = (uint8_t *)malloc(len);
	if (data == NULL)
		return NULL;

	memset(data, 0, len);

	n = i = 0;
	if (rsa == ENCRYPT_NONE) {
		data[n++] = rec->property & 0xff;
		data[n++] = rec->total & 0xff;
		for (i = 0; i < rec->total ; i++) {
			ICAR_HTONL(rec->ra[i].id);
			ICAR_HTONS(rec->ra[i].property);
			ICAR_HTONL(rec->ra[i].lulatitude);
			ICAR_HTONL(rec->ra[i].lulongitude);
			ICAR_HTONL(rec->ra[i].rdlatitude);
			ICAR_HTONL(rec->ra[i].rdlongitude);
			if (rec->ra[i].property & AREA_ATTRI_TIME) {
				memcpy(&data[n], rec->ra[i].stime, 6);
				n += 6;
				memcpy(&data[n], rec->ra[i].etime, 6);
				n += 6;
			}

			if (rec->ra[i].property & AREA_ATTRI_RATELIMIT)
				ICAR_HTONS(rec->ra[i].speed);

			if (rec->ra[i].property & AREA_ATTRI_RATELIMIT)
				data[n++] = rec->ra[i].otime & 0xff;
		}

		iovec = icar_pkg_iovec(ICAR_SET_RECTANGLE_AREA, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_delRectangle(int rsa, const char *number, struct flatDelRec *rec)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[1024] = { 0 };
	int n = 0;
	uint32_t ltmp = 0;

	if (rec == NULL || rec->total > 125)
		return NULL;

	if (rsa == ENCRYPT_NONE) {
		int i;
		data[n++] = rec->total & 0xff;
		for (i = 0; i < rec->total; i++) {
			ICAR_HTONL(rec->id[i]);
		}
		iovec = icar_pkg_iovec(ICAR_DEL_RECTANGLE_AREA, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_setPolygon(int rsa, const char *number, struct flatSetPoly *poly)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int i, n, len;
	uint32_t ltmp;
	uint16_t stmp;

	if (!poly || poly->total <= 0 || !poly->po)
		return NULL;

	for (i = 0; i < poly->total; i++)
		if (poly->po[i] == NULL)
			return NULL;

	len = sizeof(struct flatSetPoly) + poly->total * sizeof(struct point);

	data = (uint8_t *)malloc(len);
	if (data == NULL)
		return NULL;

	memset(data, 0, len);

	n = 0;
	ltmp = 0;
	stmp = 0;
	if (rsa == ENCRYPT_NONE) {
		ICAR_HTONL(poly->id);
		ICAR_HTONS(poly->property);
		if (poly->property & AREA_ATTRI_TIME) {
			memcpy(&data[n], poly->stime, 6);
			n += 6;
			memcpy(&data[n], poly->etime, 6);
			n += 6;
		}

		if (poly->property & AREA_ATTRI_RATELIMIT) {
			ICAR_HTONS(poly->speed);
			data[n++] = poly->otime & 0xff;
		}

		ICAR_HTONS(poly->total);

		for (i = 0; i < poly->total; i++) {
			ICAR_HTONL(poly->po[i]->latitude);
			ICAR_HTONL(poly->po[i]->longitude);
		}

		iovec = icar_pkg_iovec(ICAR_SET_POLYGON_AREA, number, data, n);
	}

	free(data);
	return iovec;
}


struct icar_iovec *
flat_delPolygon(int rsa, const char *number, struct flatDelPoly *poly)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[1024] = { 0 };
	int n = 0;
	uint32_t ltmp = 0;

	if (poly == NULL || poly->total > 125)
		return NULL;

	if (rsa == ENCRYPT_NONE) {
		int i;
		data[n++] = poly->total & 0xff;
		for (i = 0; i < poly->total; i++) {
			ICAR_HTONL(poly->id[i]);
		}
		iovec = icar_pkg_iovec(ICAR_DEL_POLYGON_AREA, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_setRoutine(int rsa, const char *number, struct flatSetRoute *route)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int n, i, len;
	uint32_t ltmp;
	uint16_t stmp;


	if (!route || route->total <= 0 || route->fi == NULL)
		return NULL;

	for (i = 0; i < route->total; i++)
		if (route->fi[i] == NULL)
			return NULL;

	len = sizeof(struct flatSetRoute) + route->total * sizeof(struct flatInflexion);

	data = (uint8_t *)malloc(len);
	if (data == NULL)
		return NULL;
	memset(data, 0, len);

	n = 0;
	ltmp = 0;
	stmp = 0;

	if (rsa == ENCRYPT_NONE) {
		ICAR_HTONL(route->id);
		ICAR_HTONS(route->property);
		if (route->property & AREA_ATTRI_TIME) {
			memcpy(&data[n], route->stime, 6);
			n += 6;
			memcpy(&data[n], route->etime, 6);
			n += 6;
		}

		ICAR_HTONS(route->total);

		for (i = 0; i < route->total; i++) {
			ICAR_HTONL(route->fi[i]->flexId);
			ICAR_HTONL(route->fi[i]->routeId);
			ICAR_HTONL(route->fi[i]->latitude);
			ICAR_HTONL(route->fi[i]->longitude);
			data[n++] = route->fi[i]->routeWidth & 0xff;
			data[n++] = route->fi[i]->routeAttr & 0xff;
			if (route->fi[i]->routeAttr & ROUTE_ATTR_TIME) {
				ICAR_HTONS(route->fi[i]->longThre);
				ICAR_HTONS(route->fi[i]->lackThre);
			}
			if (route->fi[i]->routeAttr & ROUTE_ATTR_RATELIMIT) {
				ICAR_HTONS(route->fi[i]->speed);
				data[n++] = route->fi[i]->otime;
			}
		}

		iovec = icar_pkg_iovec(ICAR_SET_ROUTINE, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_delRoutine(int rsa, const char *number, struct flatDelRoute *route)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[1024] = { 0 };
	int n = 0;
	uint32_t ltmp = 0;

	if (route == NULL || route->total > 125)
		return NULL;

	if (rsa == ENCRYPT_NONE) {
		int i;
		data[n++] = route->total & 0xff;
		for (i = 0; i < route->total; i++) {
			ICAR_HTONL(route->id[i]);
		}
		iovec = icar_pkg_iovec(ICAR_DEL_ROUTINE, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_repDriverInfo(int rsa, const char *number)
{
	struct icar_iovec *iovec = NULL;

	if (rsa == ENCRYPT_NONE)
	{
		iovec = icar_pkg_iovec(ICAR_REPORT_DRIVER_INFO_REQUEST, number, NULL, 0);
	}

	return iovec;
}

struct icar_iovec *
flat_multiResponse(int rsa, const char *number, struct flatMediaRes *media)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	int i, n, len;
	uint16_t stmp;
	uint32_t ltmp;

	if (media == NULL || media->total <= 0)
		return NULL;

	len = sizeof(struct flatMediaRes);
	data = (uint8_t *)malloc(len);
	if (data == NULL)
		return NULL;
	memset(data, 0, len);

	n = 0;
	stmp = 0;
	ltmp = 0;
	if (rsa == ENCRYPT_NONE)
	{
		ICAR_HTONL(media->id);
		data[n++] = media->total & 0xff;
		for (i = 0; i < media->total; i++) {
			ICAR_HTONS(media->list[i]);
		}
		iovec = icar_pkg_iovec(ICAR_MULTIMEDIA_UPLOAD_RESPONSE, number, data, n);
	}

	free(data);
	return iovec;
}

struct icar_iovec *
flat_cameraFilm(int rsa, const char *number, struct flatFilm *film)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[32] = { 0 };
	int n;

	if (!film)
		return NULL;

	n = 0;
	if (rsa == ENCRYPT_NONE) {
		data[n++] = film->channelId & 0xff;
		data[n++] = film->cmd >> 8 & 0xff;
		data[n++] = film->cmd & 0xff;
		data[n++] = film->interval >> 8 & 0xff;
		data[n++] = film->interval  & 0xff;
		data[n++] = film->mark;
		data[n++] = film->resolution;
		data[n++] = film->quality;
		data[n++] = film->bright;
		data[n++] = film->contrast;
		data[n++] = film->saturate;
		data[n++] = film->chroma;

		iovec = icar_pkg_iovec(ICAR_CAMERA_FILM_CMD, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_mediaCheck(int rsa, const char *number, struct flatMediaCheck *check)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[32] = { 0 };
	int n;

	if (!check)
		return NULL;

	n = 0;
	if (rsa == ENCRYPT_NONE) {
		data[n++] = check->type & 0xff;
		data[n++] = check->channelId & 0xff;
		data[n++] = check->opCode & 0xff;
		memcpy(&data[n], check->stime, 6);
		n += 6;
		memcpy(&data[n], check->etime, 6);
		n += 6;

		iovec = icar_pkg_iovec(ICAR_STORE_MULTIMEDIA_CHECK, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_mediaUpload(int rsa, const char *number, struct flatMediagUpload *upload)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[32] = { 0 };
	int n;

	if (!upload)
		return NULL;

	n = 0;
	if (rsa == ENCRYPT_NONE)
	{
		data[n++] = upload->type & 0xff;
		data[n++] = upload->channelId & 0xff;
		data[n++] = upload->opCode & 0xff;
		memcpy(&data[n], upload->stime, 6);
		n += 6;
		memcpy(&data[n], upload->etime, 6);
		n += 6;

		iovec = icar_pkg_iovec(ICAR_STORE_MULTIMEDIA_UPLOAD, number, data, n);
	}

	return iovec;
}

struct icar_iovec *
flat_recordCmd(int rsa, const char *number, struct flatRecordCmd *cmd)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[8] = { 0 };
	int n;

	if (cmd == NULL)
		return NULL;

	n = 0;
	if (rsa == ENCRYPT_NONE)
	{
		data[n++] = cmd->cmd & 0xff;
		data[n++] = cmd->time >> 8 & 0xff;
		data[n++] = cmd->time & 0xff;
		data[n++] = cmd->mark & 0xff;
		data[n++] = cmd->sample & 0xff;
		iovec = icar_pkg_iovec(ICAR_RECORD_START_CMD, number, data, n);
	}

	return iovec;
}

/* 单条存储多媒体数据检索上传命令 */
struct icar_iovec *
flat_retrieveUpload(int rsa, const char *number, struct flatRetrieveUp *up)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[8] = { 0 };
	int n;

	if (up == NULL)
		return NULL;

	n = 0;
	if (rsa == ENCRYPT_NONE)
	{
		uint32_t ltmp;
		ltmp = htonl(up->mediaId);
		memcpy(&data[n], &ltmp, 4);
		n += 4;
		data[n++] = up->mark & 0xff;
		iovec = icar_pkg_iovec(ICAR_SINGLE_RETRIEVE_UPLOAD, number, data, n);
	}

	return iovec;
}

/* 平台RSA公钥 */
struct icar_iovec *
flat_rsaEncry(int rsa, const char *number, struct flatRSA *r)
{
	struct icar_iovec *iovec = NULL;
	uint8_t data[256] = { 0 };
	int n;

	if (r == NULL)
		return NULL;

	n = 0;
	if (rsa == ENCRYPT_NONE) {
		uint32_t ltmp = htonl(r->e);
		memcpy(&data[n], &ltmp, 4);
		n += 4;
		memcpy(&data[n], r->n, 128);
		n += 128;

		iovec = icar_pkg_iovec(ICAR_FLAT_RSA_ENCRYPT, number, data, n);
	}

	return iovec;
}

/* 设置终端参数 */
struct icar_iovec *
set_end_param(int rsa, const char *number, struct param_list *list)
{
	struct icar_iovec *iovec = NULL;
	uint8_t *data = NULL;
	size_t size = 0;
	int i = 0;
	size_t n = 0;

	if ((number == NULL) || (list == NULL))
		return NULL;

	if (list->lsize <= 0)
		return NULL;

	for (i = 0; i < list->lsize; i++)
		size += 5 + list->list[i].len;

	size += 1;

	data = calloc(size+1, 1);
	if (data == NULL)
		icar_die("Set end param failed");

	data[n++] = list->lsize & 0xff;

	for (i = 0; i < list->lsize; i++) {
		/* 存储参数ID */
		data[n++] = list->list[i].id >> 24 & 0xff;
		data[n++] = list->list[i].id >> 16 & 0xff;
		data[n++] = list->list[i].id >> 8 & 0xff;
		data[n++] = list->list[i].id  & 0xff;
		/* 存储参数长度 */
		data[n++] = list->list[i].len  & 0xff;
		/* 存储参数值 */

		switch (list->list[i].id)
		{
		case 0x0001:
		case 0x0002:
		case 0x0003:
		case 0x0004:
		case 0x0005:
		case 0x0006:
		case 0x0007:
		case 0x0018:
		case 0x0019:
		case 0x0020:
		case 0x0021:
		case 0x0022:
		case 0x0027:
		case 0x0028:
		case 0x0029:
		case 0x002C:
		case 0x002D:
		case 0x002E:
		case 0x002F:
		case 0x0030:
		case 0x0045:
		case 0x0046:
		case 0x0047:
		case 0x0050:
		case 0x0051:
		case 0x0052:
		case 0x0053:
		case 0x0054:
		case 0x0055:
		case 0x0056:
		case 0x0057:
		case 0x0058:
		case 0x0059:
		case 0x005A:
		case 0x0064:
		case 0x0065:
		case 0x0070:
		case 0x0071:
		case 0x0072:
		case 0x0073:
		case 0x0074:
		case 0x0080:
		case 0x0093:
		case 0x0095:
		case 0x0100:
		case 0x0102:
			{
				if (list->list[i].len != 4) {
					free(data);
					return NULL;
				}
				data[n++] = list->list[i].value.l >> 24 & 0xff;
				data[n++] = list->list[i].value.l >> 16 & 0xff;
				data[n++] = list->list[i].value.l >> 8 & 0xff;
				data[n++] = list->list[i].value.l  & 0xff;
			}
			break;
		case 0x0031:
		case 0x005B:
		case 0x005C:
		case 0x005D:
		case 0x005E:
		case 0x0081:
		case 0x0082:
		case 0x0101:
		case 0x0103:
			{
				if (list->list[i].len != 2)
				{
					free(data);
					return NULL;
				}
				data[n++] = list->list[i].value.s >> 8 & 0xff;
				data[n++] = list->list[i].value.s & 0xff;
			}
			break;
		case 0x0084:
		case 0x0090:
		case 0x0091:
		case 0x0092:
		case 0x0094:
			{
				if (list->list[i].len != 1)
				{
					free(data);
					return NULL;
				}
				data[n++] = list->list[i].value.b & 0xff;
			}
			break;
		case 0x0010:
		case 0x0011:
		case 0x0012:
		case 0x0013:
		case 0x0014:
		case 0x0015:
		case 0x0016:
		case 0x0017:
		case 0x001A:
		case 0x001B:
		case 0x001C:
		case 0x001D:
		case 0x0040:
		case 0x0041:
		case 0x0042:
		case 0x0043:
		case 0x0044:
		case 0x0048:
		case 0x0049:
		case 0x0083:
			{
				if (strlen(list->list[i].value.c)+1 != list->list[i].len)
				{
					free(data);
					return NULL;
				}
				memcpy(&data[n], list->list[i].value.c, list->list[i].len);
				n += list->list[i].len;
			}
			break;

		case 0x0110:
		case 0x0111 ... 0x01FF:
			{
				if (list->list[i].len != 8)
				{
					free(data);
					return NULL;
				}
				memcpy(&data[n], list->list[i].value.c, 8);
				n += 8;
			}
		default:
			free(data);
			return NULL;
		}
	}

	if (rsa == ENCRYPT_NONE) 
		iovec = icar_pkg_iovec(ICAR_SET_END_PARAM, number, data, size);

	free(data);
	return iovec;
}

